package com.news.service.impl;

import com.news.model.NewsItem;
import com.news.model.NewsSource;
import com.news.service.NewsFetcher;
import com.news.service.NewsService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.*;
import java.util.stream.Collectors;

/**
 * 新闻服务实现类
 */
public class NewsServiceImpl implements NewsService {
    
    private static final Logger logger = LoggerFactory.getLogger(NewsServiceImpl.class);
    
    private final Map<NewsSource, NewsFetcher> fetchers;
    private final ExecutorService executorService;
    private final Map<NewsSource, List<NewsItem>> newsCache;
    private final Object cacheLock = new Object();
    
    public NewsServiceImpl() {
        this.fetchers = new HashMap<>();
        this.executorService = Executors.newFixedThreadPool(5);
        this.newsCache = new HashMap<>();
        
        // 初始化各个新闻获取器
        initializeFetchers();
    }
    
    /**
     * 初始化新闻获取器
     */
    private void initializeFetchers() {
        // 添加B站新闻获取器
        fetchers.put(NewsSource.BAIDU, new BaiduNewsFetcher());
        fetchers.put(NewsSource.BILIBILI, new BilibiliNewsFetcher());
        fetchers.put(NewsSource.TOUTIAO, new ToutiaoNewsFetcher());
        fetchers.put(NewsSource.WEIBO, new GeneralNewsFetcher(NewsSource.WEIBO));
        fetchers.put(NewsSource.ZHIHU, new GeneralNewsFetcher(NewsSource.ZHIHU));
        
        logger.info("已初始化 {} 个新闻获取器", fetchers.size());
    }
    
    @Override
    public List<NewsItem> getHotNews(NewsSource source, int limit) {
        NewsFetcher fetcher = fetchers.get(source);
        if (fetcher == null) {
            logger.warn("不支持的新闻源: {}", source);
            return new ArrayList<>();
        }
        
        // 先从缓存中获取
        synchronized (cacheLock) {
            List<NewsItem> cachedNews = newsCache.get(source);
            if (cachedNews != null && !cachedNews.isEmpty()) {
                return cachedNews.stream()
                        .limit(limit)
                        .collect(Collectors.toList());
            }
        }
        
        // 缓存中没有，从获取器获取
        List<NewsItem> news = fetcher.fetchHotNews(limit);
        
        // 更新缓存
        synchronized (cacheLock) {
            newsCache.put(source, news);
        }
        
        return news;
    }
    
    @Override
    public List<NewsItem> getAllHotNews(int limit) {
        List<NewsItem> allNews = new ArrayList<>();
        
        try {
            logger.info("开始获取所有热门新闻，限制: {} 条", limit);
            
            // 并行获取各个新闻源的数据
            List<CompletableFuture<List<NewsItem>>> futures = fetchers.entrySet().stream()
                .map(entry -> CompletableFuture.supplyAsync(() -> {
                    try {
                        NewsSource source = entry.getKey();
                        NewsFetcher fetcher = entry.getValue();
                        if (fetcher.isAvailable()) {
                            List<NewsItem> items = fetcher.fetchHotNews(limit / fetchers.size() + 2);
                            logger.info("成功获取 {} 新闻 {} 条", fetcher.getSource().getDisplayName(), items.size());
                            return items;
                        } else {
                            logger.warn("新闻源 {} 不可用", fetcher.getSource().getDisplayName());
                            return new ArrayList<NewsItem>();
                        }
                    } catch (Exception e) {
                        logger.error("获取 {} 新闻失败: {}", entry.getValue().getSource().getDisplayName(), e.getMessage());
                        return new ArrayList<NewsItem>();
                    }
                }, executorService))
                .collect(Collectors.toList());
            
            // 等待所有任务完成，使用更长的超时时间
            try {
                for (CompletableFuture<List<NewsItem>> future : futures) {
                    List<NewsItem> items = future.get(15, TimeUnit.SECONDS);
                    allNews.addAll(items);
                }
            } catch (TimeoutException e) {
                logger.warn("获取新闻超时，使用已获取的部分数据");
                // 收集已完成的结果
                for (CompletableFuture<List<NewsItem>> future : futures) {
                    if (future.isDone() && !future.isCompletedExceptionally()) {
                        try {
                            allNews.addAll(future.get(100, TimeUnit.MILLISECONDS));
                        } catch (Exception ignored) {
                            // 忽略已超时的任务
                        }
                    }
                }
            } catch (Exception e) {
                logger.error("获取新闻过程中发生异常", e);
            }
            
            // 如果没有获取到任何新闻，提供备用数据
            if (allNews.isEmpty()) {
                logger.warn("没有获取到任何新闻数据，提供备用新闻");
                allNews.addAll(getFallbackNews(limit));
            } else {
                // 按热度排序并限制数量
                allNews = allNews.stream()
                    .sorted((a, b) -> Integer.compare(b.getHotScore(), a.getHotScore()))
                    .limit(limit)
                    .collect(Collectors.toList());
            }
            
            logger.info("总共获取到 {} 条新闻", allNews.size());
            
        } catch (Exception e) {
            logger.error("获取所有热门新闻失败", e);
            // 返回备用新闻
            allNews = getFallbackNews(limit);
        }
        
        return allNews;
    }
    
    @Override
    public List<NewsItem> searchNews(String keyword, NewsSource source, int limit) {
        List<NewsItem> searchResults = new ArrayList<>();
        
        try {
            logger.info("搜索新闻，关键词: {}, 来源: {}, 限制: {} 条", keyword, 
                source != null ? source.getDisplayName() : "全部", limit);
            
            List<NewsFetcher> targetFetchers = source != null ? 
                Arrays.asList(fetchers.get(source)) : fetchers.values().stream().collect(Collectors.toList());
            
            // 并行搜索
            List<CompletableFuture<List<NewsItem>>> futures = targetFetchers.stream()
                .filter(Objects::nonNull)
                .map(fetcher -> CompletableFuture.supplyAsync(() -> {
                    try {
                        if (fetcher.isAvailable()) {
                            List<NewsItem> items = fetcher.searchNews(keyword, limit);
                            logger.info("在 {} 中搜索到 {} 条结果", 
                                fetcher.getSource().getDisplayName(), items.size());
                            return items;
                        } else {
                            logger.warn("搜索时新闻源 {} 不可用", fetcher.getSource().getDisplayName());
                            return new ArrayList<NewsItem>();
                        }
                    } catch (Exception e) {
                        logger.error("在 {} 中搜索失败: {}", 
                            fetcher.getSource().getDisplayName(), e.getMessage());
                        return new ArrayList<NewsItem>();
                    }
                }, executorService))
                .collect(Collectors.toList());
            
            // 等待搜索完成
            try {
                for (CompletableFuture<List<NewsItem>> future : futures) {
                    List<NewsItem> items = future.get(12, TimeUnit.SECONDS);
                    searchResults.addAll(items);
                }
            } catch (TimeoutException e) {
                logger.warn("搜索超时，使用已获取的部分结果");
                // 收集已完成的搜索结果
                for (CompletableFuture<List<NewsItem>> future : futures) {
                    if (future.isDone() && !future.isCompletedExceptionally()) {
                        try {
                            searchResults.addAll(future.get(100, TimeUnit.MILLISECONDS));
                        } catch (Exception ignored) {
                            // 忽略已超时的任务
                        }
                    }
                }
            }
            
            // 如果没有搜索到任何结果，提供备用搜索结果
            if (searchResults.isEmpty()) {
                logger.warn("没有搜索到任何结果，提供备用搜索结果");
                searchResults.addAll(getFallbackSearchResults(keyword, limit));
            } else {
                // 去重和排序
                searchResults = searchResults.stream()
                    .distinct()
                    .sorted((a, b) -> Integer.compare(b.getHotScore(), a.getHotScore()))
                    .limit(limit)
                    .collect(Collectors.toList());
            }
            
            logger.info("搜索完成，共找到 {} 条结果", searchResults.size());
            
        } catch (Exception e) {
            logger.error("搜索新闻失败，关键词: {}", keyword, e);
            // 返回备用搜索结果
            searchResults = getFallbackSearchResults(keyword, limit);
        }
        
        return searchResults;
    }
    
    @Override
    public void refreshNews() {
        logger.info("开始刷新所有新闻源的缓存");
        
        synchronized (cacheLock) {
            newsCache.clear();
        }
        
        // 异步刷新各个新闻源的缓存
        for (Map.Entry<NewsSource, NewsFetcher> entry : fetchers.entrySet()) {
            NewsSource source = entry.getKey();
            NewsFetcher fetcher = entry.getValue();
            
            CompletableFuture.runAsync(() -> {
                try {
                    if (fetcher.isAvailable()) {
                        List<NewsItem> news = fetcher.fetchHotNews(20);
                        synchronized (cacheLock) {
                            newsCache.put(source, news);
                        }
                        logger.info("已刷新 {} 的缓存，获取到 {} 条新闻", source.getDisplayName(), news.size());
                    }
                } catch (Exception e) {
                    logger.error("刷新 {} 缓存失败", source.getDisplayName(), e);
                }
            }, executorService);
        }
        
        logger.info("新闻缓存刷新任务已启动");
    }
    
    /**
     * 获取可用的新闻源
     */
    public List<NewsSource> getAvailableSources() {
        return fetchers.entrySet().stream()
                .filter(entry -> entry.getValue().isAvailable())
                .map(Map.Entry::getKey)
                .collect(Collectors.toList());
    }
    
    /**
     * 获取缓存的新闻数量
     */
    public Map<NewsSource, Integer> getCacheStatus() {
        Map<NewsSource, Integer> status = new HashMap<>();
        synchronized (cacheLock) {
            for (Map.Entry<NewsSource, List<NewsItem>> entry : newsCache.entrySet()) {
                status.put(entry.getKey(), entry.getValue().size());
            }
        }
        return status;
    }
    
    /**
     * 关闭服务
     */
    public void shutdown() {
        executorService.shutdown();
        try {
            if (!executorService.awaitTermination(5, TimeUnit.SECONDS)) {
                executorService.shutdownNow();
            }
        } catch (InterruptedException e) {
            executorService.shutdownNow();
        }
        logger.info("新闻服务已关闭");
    }

    /**
     * 获取备用新闻数据
     */
    private List<NewsItem> getFallbackNews(int limit) {
        List<NewsItem> fallbackNews = new ArrayList<>();
        
        String[] fallbackTitles = {
            "网络连接异常，请检查网络设置",
            "当前无法获取最新新闻，请稍后重试",
            "建议检查网络连接或DNS设置",
            "可以尝试刷新页面重新获取新闻",
            "如果问题持续，请联系技术支持"
        };
        
        for (int i = 0; i < Math.min(limit, fallbackTitles.length); i++) {
            NewsItem item = new NewsItem();
            item.setTitle(fallbackTitles[i]);
            item.setContent("由于网络问题无法获取新闻数据。请检查网络连接后重试。");
            item.setSource("系统提示");
            item.setUrl("about:blank");
            item.setPublishTime(LocalDateTime.now());
            item.setCategory("系统消息");
            item.setHotScore(1000 - i * 100);
            item.setAuthor("系统");
            
            fallbackNews.add(item);
        }
        
        logger.info("提供 {} 条备用新闻", fallbackNews.size());
        return fallbackNews;
    }
    
    /**
     * 获取备用搜索结果
     */
    private List<NewsItem> getFallbackSearchResults(String keyword, int limit) {
        List<NewsItem> fallbackResults = new ArrayList<>();
        
        NewsItem item = new NewsItem();
        item.setTitle("搜索\"" + keyword + "\"时遇到网络问题");
        item.setContent("由于网络连接问题，无法完成搜索。请检查网络连接后重试搜索。");
        item.setSource("系统提示");
        item.setUrl("https://www.baidu.com/s?wd=" + keyword);
        item.setPublishTime(LocalDateTime.now());
        item.setCategory("搜索结果");
        item.setHotScore(5000);
        item.setAuthor("系统");
        
        fallbackResults.add(item);
        
        logger.info("提供备用搜索结果");
        return fallbackResults;
    }
} 